

#region Using Statements
using System;
using System.Collections.Generic;
//using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
#endregion


//used for scene graph full of game objects
//and for each game object's component "list"

namespace Pauliver
{
  
    class GameObjectNode : Node<String,GameObject>
    {
        public GameObjectNode(String Name, GameObject gobject)
            : base(Name, gobject)
        {
        }
    }

    class GameComponentNode : Node<String, GameObject>
    {
        public GameComponentNode(String Name, GameObject gobject)
            : base(Name, gobject)
        {
        }
    }

    class Node <Key, Class> where Key:IEquatable<Key>
    {
        Node<Key, Class> _Parent;
	    List<Node<Key,Class>> _children;
	    Class _value;
	    Key _Key;

	    public Key KeyValue
	    {
		    get { return _Key; }
	    }
	    public Class ClassValue
	    {
		    get { return _value; }
	    }

	    public Node(Key _key)
        {
            this._Key = _key;
            this._value = default(Class);
            _children = new List<Node<Key, Class>>();
        }
	    public Node(Key _key,Class _value)
        {
            this._Key = _key;
            this._value = _value;
            _children = new List<Node<Key, Class>>();
        }


	    void AttachChild(Node<Key,Class> Child)
        {
            Child._Parent = this;
        }
	    public Node<Key,Class> FindFirstChild(Key _key)
        {
            if (_Key.Equals(_key))
            {
                return this;
            }
            else
            {
                foreach (Node<Key, Class> n in _children)
                {
                    if (n.FindFirstChild(_key) != null)
                    {
                        return n.FindFirstChild(_key);
                    }
                }
                return null;
            }
        }
        public Node<Key, Class> FindFirstChild(Class _class)
        {
            if (this._value.Equals( _class))
            {
                return this;
            }
            else
            {
                foreach (Node<Key, Class> n in _children)
                {
                    if (n.FindFirstChild(_value) != null)
                    {
                        return n.FindFirstChild(_value);
                    }
                }
                return null;
            }
        } //use object.equals( ) comparison
	    //public Node<Key,Class>[] FindAllChildren(Key _key){}     // use == 
	    //public Node<Key,Class>[] FindAllChildren(Class _class){} //use object.equals( ) comparison
    		
	    public void DetachChild(Node<Key,Class> Child){}
	    public void DetachChild(Key _key)
	    {
		    DetachChild(FindFirstChild(_key));
	    }
	    public void	DetachChild(Class _class)
	    {
    		DetachChild(FindFirstChild(_class));
	    }
    	public void DetachAllChildren()
        {
        
        }

	    void Update(GameTime p_Time){} //updates gameobject FIRST and gameobject updates its components, THEN update children
	    void Draw(SpriteBatch p_spritebatch,GameTime p_Time){}
    	
    }
}
